package com.xci.core.handler;

import com.xci.core.base.RestMessage;
import com.xci.core.exceptions.*;
import com.xci.core.helper.Helper;
import com.xci.core.helper.JsonHelper;
import com.xci.core.helper.SpringHelper;
import com.xci.core.helper.WebHelper;
import com.xci.core.internal.Sys;
import com.xci.sys.service.ErrorLogService;
import freemarker.core.ParseException;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.javassist.NotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * 全局异常处理器
 *
 * @author ruoyi
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 全局异常拦截处理
     */
    @ExceptionHandler(value = Exception.class)
    public Object handler(HttpServletRequest request, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        String msg = e.getMessage();
        if (e.getCause() != null) {
            msg = e.getCause().getMessage();
        }
        String errorUrl = Sys.setting().getWeb().getError500Url();
        if (e instanceof MaxUploadSizeExceededException) { //文件上传异常
            msg = "文件大小不应大于" + ((MaxUploadSizeExceededException) e).getMaxUploadSize() / 1000 + "kb";
        } else if (e instanceof ValidException) {//参数校验异常
            msg = ((ValidException) e).getMsg();
        } else if (e instanceof NotFoundException
                    ||e instanceof EntityNotFoundException) {//数据未找到异常
            msg = e.getMessage();
            errorUrl = Sys.setting().getWeb().getEntity404Url();
        } else if (e instanceof AppException
                    ||e instanceof TaskException) {//框架错误异常
            msg = e.getMessage();
        } else if (e instanceof JwtException) {//jwt解析错误异常
            msg = e.getMessage();
        } else if (e instanceof HttpRequestMethodNotSupportedException) {//请求方法不支持异常
            msg = "不支持' " + ((HttpRequestMethodNotSupportedException) e).getMethod() + "'请求";
        } else if (e instanceof UnAuthorizedException) {//未授权异常
            UnAuthorizedException ex = ((UnAuthorizedException) e);
            msg = ex.getCode() + e.getMessage();
        } else {
            saveErrorLog(e);
        }
        boolean isAjax = (WebHelper.isAjax(request) || WebHelper.isApp(request));
        if (isAjax) {
            return RestMessage.fail(msg);
        }
        if (Helper.isBlank(msg)) {
            msg = Sys.setting().getWeb().getError500AjaxMessage();
        }

        //否则返回错误页面
        modelAndView.addObject("msg", msg);
        modelAndView.addObject("exception", e);
        StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        modelAndView.addObject("exceptionMessage", stringWriter.toString());
        modelAndView.addObject("requestParams", JsonHelper.serialize(WebHelper.getRequestParamMap()));
        modelAndView.addObject("url", request.getRequestURI());
        modelAndView.setViewName(errorUrl);
        return modelAndView;
    }

    /**
     * 添加系统异常日志
     */
    private void saveErrorLog(Exception e) {
        try {
            e.printStackTrace();
            var errorLog = Sys.me().buildExceptionLog(e);
            SpringHelper.getBean(ErrorLogService.class).insert(errorLog);
        } catch (Exception ex) {
            log.error("全局异常日志保存到数据失败", ex);
            ex.printStackTrace();
        }
    }

//    /**
//     * 权限校验失败 如果请求为ajax返回json，普通请求跳转页面
//     */
//    @ExceptionHandler(AuthorizationException.class)
//    public ObjecthandleAuthorizationException(HttpServletRequest request, AuthorizationException e)
//    {
//        log.error(e.getMessage(), e);
//        if (ServletUtils.isAjaxRequest(request))
//        {
//            return AjaxResult.error(PermissionUtils.getMsg(e.getMessage()));
//        }
//        else
//        {
//            ModelAndView modelAndView = new ModelAndView();
//            modelAndView.setViewName("error/unauth");
//            return modelAndView;
//        }
//    }
//
//    /**
//     * 请求方式不支持
//     */
//    @ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
//    public AjaxResult handleException(HttpRequestMethodNotSupportedException e)
//    {
//        log.error(e.getMessage(), e);
//        return AjaxResult.error("不支持' " + e.getMethod() + "'请求");
//    }
//
//    /**
//     * 拦截未知的运行时异常
//     */
//    @ExceptionHandler(RuntimeException.class)
//    public AjaxResult notFount(RuntimeException e)
//    {
//        log.error("运行时异常:", e);
//        return AjaxResult.error("运行时异常:" + e.getMessage());
//    }
//
//    /**
//     * 系统异常
//     */
//    @ExceptionHandler(Exception.class)
//    public AjaxResult handleException(Exception e)
//    {
//        log.error(e.getMessage(), e);
//        return AjaxResult.error("服务器错误，请联系管理员");
//    }
//


    // /*
    //  *  400-Bad Request
    //  */
    // @ResponseStatus(HttpStatus.BAD_REQUEST)
    // @ExceptionHandler(HttpMessageNotReadableException.class)
    // public Response handleHttpMessageNotReadableException(
    //         HttpMessageNotReadableException e) {
    //     log.error("无法读取JSON...", e);
    //     return new Response().failure("无法读取JSON");
    // }
    //
    // @ResponseStatus(HttpStatus.BAD_REQUEST)
    // @ExceptionHandler(MethodArgumentNotValidException.class)
    // public Response handleValidationException(MethodArgumentNotValidException e)
    // {
    //     log.error("参数验证异常...", e);
    //     return new Response().failure("参数验证异常");
    // }
    //
    //
    // /*
    //  * 405 - method Not allowed
    //  * HttpRequestMethodNotSupportedException 是ServletException 的子类，需要Servlet API 支持
    //  *
    //  */
    // @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    // @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    // public Response handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
    //     log.error("不合法的请求方法...",e);
    //     return new Response().failure("不合法的请求方法");
    // }
    //
    // /**
    //  * 415-Unsupported Media Type.HttpMediaTypeNotSupportedException是ServletException的子类，需要Serlet API支持
    //  */
    // @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    // @ExceptionHandler({ HttpMediaTypeNotSupportedException.class })
    // public Response handleHttpMediaTypeNotSupportedException(Exception e) {
    //     log.error("内容类型不支持...", e);
    //     return new Response().failure("内容类型不支持");
    // }
    //
    // /* *//**
    //  * 500 - Internal Server Error
    //  *//*
    // @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    // @ExceptionHandler(TokenException.class)
    // public Response handleTokenException(Exception e) {
    //     log.error("令牌无效...", e);
    //     return new Response().failure("令牌无效");
    // }*/
    //


}